using System.Collections.Generic;
using System.Linq;

namespace ExtendedMvc.Elements {
	public class ValidationSummary<TModel> : ValidationSummaryBase<ValidationSummary<TModel>, TModel> where TModel : class {
		public ValidationSummary(IModelViewHelper<TModel> helper) : base(helper) { }
	}

	public abstract class ValidationSummaryBase<T, TModel> : Region<T>
		where T : ValidationSummaryBase<T, TModel>
		where TModel : class {
		private UnorderedList _ul;
		private bool _excludePropertyErrors;
		private string _defaultMessage;
		private IModelViewHelper<TModel> _helper;

		protected IModelViewHelper<TModel> helper { get { return _helper; } }

		protected ValidationSummaryBase(IModelViewHelper<TModel> helper, string message = null)
			: base(null) {
			_helper = helper;
			_ul = new UnorderedList();
			_excludePropertyErrors = false;
			DefaultMessage(message);
		}

		public virtual T ExcludePropertyErrors(bool value = true) {
			_excludePropertyErrors = value;
			return (T)this;
		}

		public virtual T DefaultMessage(string value) {
			_defaultMessage = value;
			return (T)this;
		}

		protected virtual bool HasError {
			get {
				return (_helper.ViewContext.ViewData.ModelState != null && _helper.ViewContext.ViewData.ModelState.Any(k => k.Value.Errors != null && k.Value.Errors.Any()));
			}
		}

		protected virtual IEnumerable<string> ErrorMessages {
			get {
				if (!HasError) return null;
				if (_excludePropertyErrors) return _helper.ViewContext.ViewData.ModelState.Where(k => k.Key == "").SelectMany(k => k.Value.Errors.Select(e => e.ErrorMessage));
				else return _helper.ViewContext.ViewData.ModelState.SelectMany(k => k.Value.Errors.Select(e => e.ErrorMessage));
			}
		}

		protected override void Prepare() {
			CssClass("validation-summary-errors");
			base.Prepare();
		}

		protected override void SetContent() {
			if (!string.IsNullOrEmpty(_defaultMessage)) _ul.AddBefore(new Literal(_defaultMessage).ToString());
			ErrorMessages.ToList().ForEach(m => { _ul.AddItem(m); });
			Builder.InnerHtml = _ul.ToString();
		}

		public override string ToString() {
			if (!HasError) return string.Empty;
			return base.ToString();
		}
	}
}